package cn.xo68.boot.auth.core;

import cn.xo68.core.util.StringTools;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.Map;

/**
 *  web 工具类
 */
public final class WebContextUtils {

    /**
     * 代理，负载ip 头信息name
     */
    public static final String HEADER_FORWARDED_FOR="x-forwarded-for";

    public static final String HEADER_REAL_IP="X-Real-IP";

    public static final String UNKNOWN="unknown";

    /**
     * 返回真实IP地址
     * @param request
     * @return
     */
    public static String getRealRemoteIpAddress(HttpServletRequest request){
        String realRemoteIp=StringTools.EMPTY;
        String forwardedIp = request.getHeader(HEADER_FORWARDED_FOR);

        if (StringTools.isNotEmpty(forwardedIp) && !UNKNOWN.equalsIgnoreCase(forwardedIp)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if( forwardedIp.indexOf(",")!=-1 ){
                String[] forwardedIps = forwardedIp.split(",");
                for(String fIp : forwardedIps){
                    if(!UNKNOWN.equalsIgnoreCase(fIp)){
                        realRemoteIp=fIp;
                    }
                }
            }
        }
        if (StringTools.isEmpty(realRemoteIp) || UNKNOWN.equalsIgnoreCase(realRemoteIp)) {
            realRemoteIp = request.getHeader("Proxy-Client-IP");
        }

        if (StringTools.isEmpty(realRemoteIp) || UNKNOWN.equalsIgnoreCase(realRemoteIp)) {
            realRemoteIp = request.getHeader("WL-Proxy-Client-IP");
        }

        if (StringTools.isEmpty(realRemoteIp) || UNKNOWN.equalsIgnoreCase(realRemoteIp)) {
            realRemoteIp = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringTools.isEmpty(realRemoteIp) || UNKNOWN.equalsIgnoreCase(realRemoteIp)) {
            realRemoteIp = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringTools.isEmpty(realRemoteIp) || UNKNOWN.equalsIgnoreCase(realRemoteIp)) {
            realRemoteIp = request.getHeader(HEADER_REAL_IP);
        }
        if (StringTools.isNotEmpty(realRemoteIp) && !UNKNOWN.equalsIgnoreCase(realRemoteIp)) {
            return realRemoteIp;
        }

        return request.getRemoteAddr();
    }

    /**
     * 获取客户端唯一凭证
     * @param request
     * @return
     */
    public static String getClientPrincipal(HttpServletRequest request){
        String realIp=getRealRemoteIpAddress(request);
        String userAgent=request.getHeader("User-Agent");
        return MessageFormat.format("{0}${1}",realIp, userAgent);
    }

    /**
     * 请求的完整路径
     * @param request
     * @return
     */
    public static String getRequestUrl(HttpServletRequest request){
        StringBuilder urlSb=new StringBuilder();
        urlSb.append(request.getScheme());
        urlSb.append("://");
        urlSb.append(request.getServerName());
        if(request.getServerPort()!=80){
            urlSb.append(":"+request.getServerPort());
        }
        urlSb.append(request.getContextPath());
        urlSb.append(request.getServletPath());
        if(StringTools.isNotEmpty(request.getQueryString())){
            urlSb.append("?"+request.getQueryString());
        }
        //request.get

        return urlSb.toString();
    }

    /**
     * urlEncode
     * @param input
     * @param encodingScheme
     * @return
     */
    public static String urlEncode(String input, String encodingScheme) {
        try {
            return URLEncoder.encode(input, encodingScheme);
        } catch (UnsupportedEncodingException e) {
            //e.printStackTrace();
        }
        return StringTools.EMPTY;
    }

    /**
     * url 增加 query参数
     * @param url
     * @param queryParams
     * @return
     */
    public static String appendQuery(String url, Map<String,String> queryParams){
        return appendQuery(url,queryParams,"UTF-8");
    }
    /**
     * url 增加 query参数
     * @param url
     * @param queryParams
     * @param encodingScheme
     * @return
     */
    public static String appendQuery(String url, Map<String,String> queryParams, String encodingScheme){

        StringBuilder targetUrl = new StringBuilder();
        targetUrl.append(url);

        String fragment = null;
        int anchorIndex = targetUrl.toString().indexOf('#');
        if (anchorIndex > -1) {
            fragment = targetUrl.substring(anchorIndex);
            targetUrl.delete(anchorIndex, targetUrl.length());
        }

        // If there aren't already some parameters, we need a "?".
        boolean first = (url.indexOf('?') < 0);
        //Map queryProps = queryProperties(model);

        if (queryParams != null) {
            for (Object o : queryParams.entrySet()) {
                if (first) {
                    targetUrl.append('?');
                    first = false;
                } else {
                    targetUrl.append('&');
                }
                Map.Entry entry = (Map.Entry) o;
                String encodedKey = urlEncode(entry.getKey().toString(), encodingScheme);
                String encodedValue =
                        (entry.getValue() != null ? urlEncode(entry.getValue().toString(), encodingScheme) : "");
                targetUrl.append(encodedKey).append('=').append(encodedValue);
            }
        }

        // Append anchor fragment, if any, to end of URL.
        if (fragment != null) {
            targetUrl.append(fragment);
        }
        return targetUrl.toString();
    }
}
